/**
* @file server.c
* @brief HPSDR server application
* @author John Melton, G0ORX/N6LYT
* @version 0.1
* @date 2009-10-13
*/


/* Copyright (C)
* 2009 - John Melton, G0ORX/N6LYT
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
*
*/

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <pthread.h>
#include <string.h>
#include <getopt.h>

#include <usb.h>

#include "client.h"
#include "listener.h"
#include "softrock.h"
#include "receiver.h"
#include "operations.h"
#include "pmsdr_com.h"

const enum optVal {
   SAMPLERATE = 0,
   DEVICE     = 1,
   INPUT      = 2,
   OUTPUT     = 3,
   IQ         = 4,
   QI         = 5,
   SI570      = 6,
   VERBOSE    = 7,
   STARTUPFREQ = 8,
   MULTIPLIER = 9,
   CORRECTEDFREQ = 10,
   SERIALID   = 11,
   HELP       = 12,
   PMSDR      = 13,
} optVal;

static struct {
    int         opt_index;
    const char *msg;
} hlpTbl[] = {
    { SAMPLERATE, "defines the sample rate in Samples per second" },
    { DEVICE,     "device to use" },
    { INPUT,      "index of input device to be used"},
    { OUTPUT,      "index of output device to be used"},
    { IQ,          ""},    
    { QI,          ""},
    { SI570,       "uses Si570 to change frequency in QSD hardware" },
    { VERBOSE,     "verbose output"},
    { STARTUPFREQ, ""},
    { MULTIPLIER,  ""},
    { CORRECTEDFREQ,""},
    { SERIALID,    ""},
    { HELP,        "this help" },
    { PMSDR,       "uses PMSDR hardware"},
};


static struct option long_options[] = {
    {"samplerate",required_argument, 0, SAMPLERATE},
    {"device",required_argument, 0, DEVICE},
    {"input",required_argument, 0, INPUT},
    {"output",required_argument, 0, OUTPUT},
    {"iq",no_argument, 0, IQ},
    {"qi",no_argument, 0, QI},
    {"si570",no_argument, 0, SI570},
    {"verbose",no_argument, 0, VERBOSE},
    {"startupfreq",required_argument, 0, STARTUPFREQ},
    {"multiplier",required_argument, 0, MULTIPLIER},
    {"correctedfreq",required_argument, 0, CORRECTEDFREQ},
    {"serialid",required_argument, 0, SERIALID},
    {"help",no_argument, 0, HELP},
    {"pmsdr",no_argument, 0, PMSDR},

};

static char* short_options="sd";
static int option_index;

void usage(void)
{
   int i;
   fprintf (stderr, "Usage:\n");
   for (i=0; i<(sizeof(hlpTbl)/sizeof(hlpTbl[0])); ++i) {
      fprintf (stderr, "  --%s:\t\t%s\n", long_options[i].name, hlpTbl[i].msg);
   }   
}

int si570=0;
int pmsdr=0;
int verbose=0;
double startupFreq=56.32;
double multiplier=4;
int i2cAddress = 0x55;
double fXtall = 114.285;
char* usbSerialID=NULL;

usb_dev_handle* handle = NULL;

void process_args(int argc,char* argv[]);

int main(int argc,char* argv[]) {

    int rc;

    softrock_set_device("/dev/dsp");

    process_args(argc,argv);

    if(si570) {
        usb_init();
        rc=usbOpenDevice(&handle,0x16C0,"www.obdev.at",0x05DC,"DG8SAQ-I2C",usbSerialID);
        if(rc!=0) {
            fprintf(stderr,"Cannot open Softrock USB device\n");
            exit(1);
        }
    }

    if(pmsdr) {
        if (pmsdr_init()) {
           fprintf(stderr,"Cannot initialize PMSDR hardware.\n");
           exit (2);
        }
    }    

    init_receivers();

    create_listener_thread();

    create_softrock_thread();

    while(1) {
        if (getchar() == 'q') {
           fprintf (stderr, "\nClosing....\n");
           break;
        } else 
           sleep(2);
    }

    if(pmsdr) {
        if (pmsdr_terminate()) {
           exit (2);
        }
    }     
    fprintf (stderr, "\n");
}

void process_args(int argc,char* argv[]) {
    int i;

    // set defaults
    softrock_set_receivers(1);
    softrock_set_sample_rate(96000);
    //softrock_set_device("/dev/dsp");

    while((i=getopt_long(argc,argv,short_options,long_options,&option_index))!=EOF) {
        switch(option_index) {
            case SAMPLERATE: // sample rate
fprintf(stderr,"process_args: samplerate=%s\n",optarg);
                softrock_set_sample_rate(atoi(optarg));
                break;
            case DEVICE: // device
fprintf(stderr,"process_args: device=%s\n",optarg);
                softrock_set_device(optarg);
                break;
            case INPUT: // input
fprintf(stderr,"process_args: input=%s\n",optarg);
                softrock_set_input(optarg);
                break;
            case OUTPUT: // output
fprintf(stderr,"process_args: output=%s\n",optarg);
                softrock_set_output(optarg);
                break;
            case IQ: // iq
                softrock_set_iq(1);
                break;
            case QI: // qi
                softrock_set_iq(0);
                break;
            case SI570: // si570
                si570=1;
                break;
            case VERBOSE: // verbose
                verbose=1;
                break;
            case 8: // startupfreq
                startupFreq=atof(optarg);
                break;
            case 9: // multiplier
                multiplier=atof(optarg);
                break;
            case 10: // corrected xtal freq
                fXtall=atof(optarg);
                break;
            case 11: // serial ID
                usbSerialID=optarg;
                break;
            case HELP:
                usage();
                exit (255);
                break;
            case PMSDR: // PMSDR hardware
                pmsdr=1;
                break;
            default:
                fprintf(stderr,"invalid argument\n");
                exit(1);
        }
    }
}

